package MathTextModeller
{
	import MathText.WordProblem;
	
	import MyDisplayObjects.ClickableMCEvent;
	import MyDisplayObjects.DraggableMC;
	import MyDisplayObjects.MyButton;
	import MyDisplayObjects.TextFeedbackDisplay;
	
	import TaskStructure.LogEvent;
	import TaskStructure.WordProblemItem;
	
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.text.TextField;
	import flash.text.TextFormat;
	import flash.utils.getQualifiedClassName;
	
	/** An object of this class provides a space to model sentences (SentenceDisplay) and a set of tools to create that model (SentenceTools),
	 *  and a button to press when completed.
	 */
	public class SentenceModeller extends MovieClip
	{
		// static constants
		public static const SENTENCE_DISPLAY_HEIGHT_PROP:Number = .8;
		// private vars, inaccessible outside of class
		private var optionsXML:XML, imagesContextXML:XML, errorsXML:XML;
		private var wordProblem:WordProblem;
		private var sentenceIndex:int;
		private var _sentenceDisplay:SentenceDisplay;
		private var toolDisplay:ToolDisplay;
		private var textFeedbackDisplay:TextFeedbackDisplay;
		private var continueButton:MyButton;
		private var trashTField:TextField;
		
		public function get sentenceDisplay():SentenceDisplay{return _sentenceDisplay;}
		public function get currentFaceType():String{return toolDisplay.currentFaceType;}
		
		/** This constructor can be used to create a new sentence display or instantiate an old one */
		public function SentenceModeller(width:Number, height:Number, wordProblem:WordProblem, sentenceIndex:int, optionsXML:XML, imagesContextXML:XML, errorsXML:XML, initialToolDisplay:String="", osentenceDisplay:SentenceDisplay = null)
		{
			this.graphics.drawRect(0, 0, width, height);
			this.wordProblem = wordProblem;
			this.sentenceIndex = sentenceIndex;
			this.optionsXML = optionsXML;
			this.imagesContextXML = imagesContextXML;
			this.errorsXML = errorsXML;
			// tools
			toolDisplay = new ToolDisplay (this.width - width/wordProblem.numSentencesToModel*2, height, new Array("combine", "change", "compare"), optionsXML.child("tools")[0], imagesContextXML..tools[0], wordProblem, initialToolDisplay);
			toolDisplay.addEventListener(ClickableMCEvent.CLICKED, handleToolClicked);
			this.addChild(toolDisplay);
			// space for model
			if (osentenceDisplay == null)
			{
				_sentenceDisplay = new SentenceDisplay (width/wordProblem.numSentencesToModel*2*SENTENCE_DISPLAY_HEIGHT_PROP, height*SENTENCE_DISPLAY_HEIGHT_PROP, wordProblem);
				if (imagesContextXML..display[0].child("background").length() > 0) _sentenceDisplay.addImageToDisplay(imagesContextXML..display[0]..background[0], "background", false);
				// name sentence display
				if (sentenceIndex == 0){_sentenceDisplay.name = "left";}
				else if (sentenceIndex == 1){_sentenceDisplay.name = "middle";}
				else if (sentenceIndex == 2){_sentenceDisplay.name = "right";}
			} else
			{
				_sentenceDisplay = osentenceDisplay;
			}
			_sentenceDisplay.addEventListener(Event.REMOVED, handleObjectRemovedFromSentenceDisplay);
			_sentenceDisplay.x = toolDisplay.x + toolDisplay.width;
			
			// place a text field for feedback on display object
			textFeedbackDisplay = new TextFeedbackDisplay(sentenceDisplay.width, this.height-sentenceDisplay.height, sentenceDisplay.width/20, sentenceDisplay.width/20, this.width/50, 0x444444, 0xEEEEEE, "Can you make a picture of the sentence in white?"); 
			textFeedbackDisplay.x = sentenceDisplay.x;
			textFeedbackDisplay.y = sentenceDisplay.y + sentenceDisplay.height;
			this.addChild(textFeedbackDisplay);
			
			// place a continue button, place a listener so when completed this completes as well.
			continueButton = new MyButton(this.width-toolDisplay.width-textFeedbackDisplay.width-textFeedbackDisplay.height/10, textFeedbackDisplay.height-textFeedbackDisplay.height/10, textFeedbackDisplay.height/10, textFeedbackDisplay.height/10, "I'm finished.", 0x008800, 2);
			continueButton.addEventListener(MouseEvent.CLICK, handleContinuePressed);
			this.addChild(continueButton);
			continueButton.x = textFeedbackDisplay.x + textFeedbackDisplay.width;
			continueButton.y = textFeedbackDisplay.y;
			
			trashTField = new TextField();
			trashTField.selectable = false;
			trashTField.mouseEnabled = false;
			trashTField.defaultTextFormat = new TextFormat("Arial", this.width/35, 0xFFFFFF, null, null, null, null, null, "center");
			trashTField.text = "Move objects here to remove them.";
			trashTField.multiline = true;
			trashTField.wordWrap = true;
			trashTField.background = true;
			trashTField.backgroundColor = 0xFFAAAA;
			trashTField.width = this.width  - (_sentenceDisplay.x + _sentenceDisplay.width);
			trashTField.x = _sentenceDisplay.x + _sentenceDisplay.width;
			trashTField.height = this.height - (textFeedbackDisplay.height);
			this.addChild(trashTField);
			
			this.addChild(_sentenceDisplay);
			
		}
				
		//////////////////////////// INTERACTION BETWEEN TOOL AND MODEL DISPLAY ////////////////////////////////////
		/** This function handles a click on one of the buttons on the tool face */
		private function handleToolClicked (event:ClickableMCEvent):void
		{
			event.stopPropagation();  // a bubbling event, stop propogation
			_sentenceDisplay.addImageToDisplay(imagesContextXML..display.child(toolDisplay.currentFaceType).child(event.name)[0], event.name, true); 
		}
		
		private function handleObjectRemovedFromSentenceDisplay (event:Event):void
		{
			// for objects being removed from display, not for removing the display itself
			if (flash.utils.getQualifiedClassName(event.target) == "MyDisplayObjects::DraggableMC" || flash.utils.getQualifiedClassName(event.target) == "MyDisplayObjects::DraggableImage" || flash.utils.getQualifiedClassName(event.target) == "MyDisplayObjects::DraggableShape")
			{
				toolDisplay.enableButton(DraggableMC(event.target).name);
			} 
		}
		
		///////////////////////////////////////////////////// FOR COMPLETION //////////////////////////////////////////////////
		/** When user clicks the continue button dispatch complete event */
		private function handleContinuePressed (event:MouseEvent):void
		{
			continueButton.removeEventListener(MouseEvent.CLICK, handleContinuePressed);
			event.stopPropagation();
			if (checkFinalConditions())
			{
				this.dispatchEvent(new LogEvent(LogEvent.TRANSITION, "continue", sentenceDisplay.name, continueButton.x, continueButton.y));
				complete();
			} else
			{
				continueButton.addEventListener(MouseEvent.CLICK, handleContinuePressed);				
			}
		}
		
		/** Have we met final conditions (mainly, is the number model correct and does it match the problem) */
		private function checkFinalConditions ():Boolean
		{
			var node:XML;
			if (errorsXML..sentenceModel..error.(attribute("id")=="NO_SUBJECT").length() > 0)
			{
				node = errorsXML..sentenceModel..error.(attribute("id")=="NO_SUBJECT")[0];
				// make sure it is enabled
				if (node.attribute("enabled") != "false" && node.attribute("halting") != "false")
				{
					if (_sentenceDisplay.numOthers == 0)
					{
						textFeedbackDisplay.newFeedback(node.toString());
						return false;
					}
				}
			} 
			if (errorsXML..sentenceModel..error.(attribute("id")=="NO_QUANTITY").length() > 0)
			{
				node = errorsXML..sentenceModel..error.(attribute("id")=="NO_QUANTITY")[0];
				// make sure it is enabled
				if (node.attribute("enabled") != "false" && node.attribute("halting") != "false")
				{
					if (_sentenceDisplay.numUnits + _sentenceDisplay.numVariables == 0)
					{
						textFeedbackDisplay.newFeedback(node.toString());
						return false;
					}
				}
			} 
			if (errorsXML..sentenceModel..error.(attribute("id")=="NONMATCHING_NUMBER").length() > 0)
			{
				node = errorsXML..sentenceModel..error.(attribute("id")=="NONMATCHING_NUMBER")[0];
				// make sure it is enabled
				if (node.attribute("enabled") != "false" && node.attribute("halting") != "false")
				{
					
					if (String(wordProblem.sentences[sentenceIndex]).search(String(_sentenceDisplay.numUnits)) == -1 && String(wordProblem.sentences[sentenceIndex]).search(RegExp(/[0-9]+/)) != -1)
					{
						textFeedbackDisplay.newFeedback(node.toString());
						return false;
					}
				}
			} 
			if (errorsXML..sentenceModel..error.(attribute("id")=="COMPARE_WRONG_SIDE").length() > 0 && sentenceDisplay.hasCompare)
			{
				node = errorsXML..sentenceModel..error.(attribute("id")=="COMPARE_WRONG_SIDE")[0];
				if (node.attribute("enabled") != "false" && node.attribute("halting") != "false")
				{
					// WHO HAS MORE?
					var i:uint; var unitMC:DraggableMC;
					if (wordProblem.subject1.getQuantity() > wordProblem.subject2.getQuantity())
					{ // subject1 has more, should be more object on right side
						for (i; i < sentenceDisplay.numUnits; i++)
						{
							unitMC = sentenceDisplay.getUnitAt(i);
							if (unitMC.x < (sentenceDisplay.width/2 - unitMC.width)) 
							{
								textFeedbackDisplay.newFeedback(node.toString());
								return false;
							}
						}
					} else if (wordProblem.subject1.getQuantity() < wordProblem.subject2.getQuantity())
					{ // subject1 has more, should be more object on left side
						for (i; i < sentenceDisplay.numUnits; i++)
						{
							unitMC = sentenceDisplay.getUnitAt(i);
							if (unitMC.x > sentenceDisplay.width/2) 
							{
								textFeedbackDisplay.newFeedback(node.toString());
								return false;
							}
						}
					} 
				}
			}
			return true;
		}
		
		private function complete():void
		{
			_sentenceDisplay.removeEventListener(Event.REMOVED, handleObjectRemovedFromSentenceDisplay);
			this.dispatchEvent (new Event(Event.COMPLETE));
		}
	}
}